package it.biffi.jirc.bot;

import it.biffi.jirc.bot.event.ConnectionEvent;
import it.biffi.jirc.bot.event.FileTransferStartEvent;
import it.biffi.jirc.bot.event.FileTrasnferFinishEvent;
import it.biffi.jirc.bot.event.GenericEvent;
import it.biffi.jirc.bot.event.JoinEvent;
import it.biffi.jirc.bot.event.MessageEvent;
import it.biffi.jirc.bot.listener.AbstractListener;
import it.biffi.jirc.bot.listener.EventListenerManager;

import java.io.IOException;

import org.jibble.pircbot.DccFileTransfer;
import org.jibble.pircbot.IrcException;
import org.jibble.pircbot.NickAlreadyInUseException;
import org.jibble.pircbot.PircBot;

public class AbstractPircBot implements Bot {

	private InnerBot bot;

	private EventListenerManager ebus;

	private BotClientConfig config;

	public AbstractPircBot() {
		ebus = new EventListenerManager();
	}

	@Override
	public synchronized void start(BotConfig config) throws BotException {

		this.config = (BotClientConfig) config;
		if (bot == null) {
			bot = new InnerBot();
		}
		bot.setAutoNickChange(true);
		bot.setVerbose(this.config.isVerbose());

		// Connect to the IRC server.
		try {
			bot.connect(this.config.getServer());
		} catch (NickAlreadyInUseException e) {
			throw new BotException(e.getMessage(), e);
		} catch (IOException e) {
			throw new BotException(e.getMessage(), e);
		} catch (IrcException e) {
			throw new BotException(e.getMessage(), e);
		}

	}

	@Override
	public synchronized void stop() {
		// TODO: clean ebus
		bot.disconnect();

	}

	protected final class InnerBot extends PircBot {

		public InnerBot() {
			this.setName(AbstractPircBot.this.config.getNick());
			this.setAutoNickChange(true);
		}

		@Override
		protected void onConnect() {
			ebus.addEvent(new ConnectionEvent());
		}

		@Override
		protected void onJoin(String channel, String sender, String login,
				String hostname) {
			JoinEvent event = new JoinEvent();
			event.putData(JoinEvent.CHANNEL, channel);
			event.putData(JoinEvent.SENDER, sender);
			event.putData(JoinEvent.LOGIN, login);
			event.putData(JoinEvent.HOSTNAME, hostname);
			ebus.addEvent(event);
		}

		@Override
		protected void onIncomingFileTransfer(DccFileTransfer transfer) {
			System.out.println("<<<<<<onIncomingFileTransfer>>>>>>");
			FileTransferStartEvent event = new FileTransferStartEvent();
			ebus.addEvent(event, transfer);
			super.onIncomingFileTransfer(transfer);
		}

		@Override
		protected void onMessage(String channel, String sender, String login,
				String hostname, String message) {
			// System.out.println("onMessage: " + sender + " - " + message);
			MessageEvent event = new MessageEvent();
			event.putData(MessageEvent.CHANNEL, channel);
			event.putData(MessageEvent.SENDER, sender);
			event.putData(MessageEvent.LOGIN, login);
			event.putData(MessageEvent.HOSTNAME, hostname);
			event.putData(MessageEvent.MESSAGE, message);
			ebus.addEvent(event);
			super.onMessage(channel, sender, login, hostname, message);
		}

		@Override
		protected void onPrivateMessage(String sender, String login,
				String hostname, String message) {
			MessageEvent event = new MessageEvent();
			event.putData(MessageEvent.SENDER, sender);
			event.putData(MessageEvent.LOGIN, login);
			event.putData(MessageEvent.HOSTNAME, hostname);
			event.putData(MessageEvent.MESSAGE, message);
			ebus.addEvent(event);
		}

		@Override
		protected void onFileTransferFinished(DccFileTransfer transfer,
				Exception e) {
			System.out.println("<<<<<<onFileTransferFinished>>>>>>");
			FileTrasnferFinishEvent event = new FileTrasnferFinishEvent();
			ebus.addEvent(event, e);
		}
	}

	public InnerBot getBot() {
		return bot;
	}

	@Override
	public void addEventListener(GenericEvent event,
			AbstractListener<?> listener) {
		ebus.addEventListener(event, listener);

	}

	public EventListenerManager getEbus() {
		return ebus;
	}

	@Override
	public void sendMessage(String to, String msg) {
		bot.sendMessage(to, msg);

	}

}
